import type { Point, Transform } from './types';

export class TransformManager {
  constructor() {
    // 初始化变换管理器
    console.log('TransformManager initialized');
  }

  /**
   * 应用变换到Canvas上下文
   */
  static applyTransform(
    ctx: CanvasRenderingContext2D,
    transform: Transform,
  ): void {
    ctx.translate(transform.position.x, transform.position.y);
    ctx.rotate(transform.rotation);
    ctx.scale(transform.scale.x, transform.scale.y);
  }

  /**
   * 将世界坐标转换为局部坐标
   */
  static worldToLocal(point: Point, transform: Transform): Point {
    const cos = Math.cos(-transform.rotation);
    const sin = Math.sin(-transform.rotation);

    const dx = point.x - transform.position.x;
    const dy = point.y - transform.position.y;

    return {
      x: (dx * cos - dy * sin) / transform.scale.x,
      y: (dx * sin + dy * cos) / transform.scale.y,
    };
  }

  /**
   * 将局部坐标转换为世界坐标
   */
  static localToWorld(point: Point, transform: Transform): Point {
    const cos = Math.cos(transform.rotation);
    const sin = Math.sin(transform.rotation);

    const x = point.x * transform.scale.x;
    const y = point.y * transform.scale.y;

    return {
      x: transform.position.x + x * cos - y * sin,
      y: transform.position.y + x * sin + y * cos,
    };
  }

  /**
   * 组合两个变换
   */
  static compose(transformA: Transform, transformB: Transform): Transform {
    // 先应用B的变换，再应用A的变换
    const worldPoint = TransformManager.localToWorld(
      transformB.position,
      transformA,
    );

    return {
      position: worldPoint,
      rotation: transformA.rotation + transformB.rotation,
      scale: {
        x: transformA.scale.x * transformB.scale.x,
        y: transformA.scale.y * transformB.scale.y,
      },
      anchor: {
        x: (transformA.anchor.x + transformB.anchor.x) / 2,
        y: (transformA.anchor.y + transformB.anchor.y) / 2,
      },
    };
  }

  /**
   * 计算变换的逆变换
   */
  static inverse(transform: Transform): Transform {
    const cos = Math.cos(-transform.rotation);
    const sin = Math.sin(-transform.rotation);

    const dx = -transform.position.x;
    const dy = -transform.position.y;

    return {
      position: {
        x: (dx * cos - dy * sin) / transform.scale.x,
        y: (dx * sin + dy * cos) / transform.scale.y,
      },
      rotation: -transform.rotation,
      scale: {
        x: 1 / transform.scale.x,
        y: 1 / transform.scale.y,
      },
      anchor: {
        x: 1 - transform.anchor.x,
        y: 1 - transform.anchor.y,
      },
    };
  }

  /**
   * 插值两个变换
   */
  static interpolate(
    transformA: Transform,
    transformB: Transform,
    t: number,
  ): Transform {
    return {
      position: {
        x:
          transformA.position.x +
          (transformB.position.x - transformA.position.x) * t,
        y:
          transformA.position.y +
          (transformB.position.y - transformA.position.y) * t,
      },
      rotation:
        transformA.rotation + (transformB.rotation - transformA.rotation) * t,
      scale: {
        x: transformA.scale.x + (transformB.scale.x - transformA.scale.x) * t,
        y: transformA.scale.y + (transformB.scale.y - transformA.scale.y) * t,
      },
      anchor: {
        x:
          transformA.anchor.x + (transformB.anchor.x - transformA.anchor.x) * t,
        y:
          transformA.anchor.y + (transformB.anchor.y - transformA.anchor.y) * t,
      },
    };
  }

  /**
   * 获取变换矩阵
   */
  static getMatrix(transform: Transform): DOMMatrix {
    const matrix = new DOMMatrix();
    matrix.translateSelf(transform.position.x, transform.position.y);
    matrix.rotateSelf((transform.rotation * 180) / Math.PI);
    matrix.scaleSelf(transform.scale.x, transform.scale.y);
    return matrix;
  }

  /**
   * 从矩阵创建变换
   */
  static fromMatrix(matrix: DOMMatrix): Transform {
    // 提取变换参数
    const position = { x: matrix.e, y: matrix.f };

    // 计算旋转角度
    const rotation = Math.atan2(matrix.b, matrix.a);

    // 计算缩放
    const scaleX = Math.sqrt(matrix.a * matrix.a + matrix.b * matrix.b);
    const scaleY = Math.sqrt(matrix.c * matrix.c + matrix.d * matrix.d);

    return {
      position,
      rotation,
      scale: { x: scaleX, y: scaleY },
      anchor: { x: 0.5, y: 0.5 },
    };
  }

  /**
   * 约束变换（用于保持比例等）
   */
  static constrainTransform(
    transform: Transform,
    constraints: {
      maintainAspectRatio?: boolean;
      minScale?: number;
      maxScale?: number;
      snapRotation?: number; // 角度间隔
    } = {},
  ): Transform {
    const result = { ...transform };

    // 保持宽高比
    if (constraints.maintainAspectRatio) {
      const avgScale = (result.scale.x + result.scale.y) / 2;
      result.scale.x = avgScale;
      result.scale.y = avgScale;
    }

    // 限制缩放范围
    if (constraints.minScale !== undefined) {
      result.scale.x = Math.max(constraints.minScale, result.scale.x);
      result.scale.y = Math.max(constraints.minScale, result.scale.y);
    }

    if (constraints.maxScale !== undefined) {
      result.scale.x = Math.min(constraints.maxScale, result.scale.x);
      result.scale.y = Math.min(constraints.maxScale, result.scale.y);
    }

    // 角度吸附
    if (constraints.snapRotation !== undefined) {
      const snapAngle = (constraints.snapRotation * Math.PI) / 180;
      result.rotation = Math.round(result.rotation / snapAngle) * snapAngle;
    }

    return result;
  }
}

export default TransformManager;
